What is JSON injection?

JSON injection is a vulnerability that lets a malicious hacker inject malicious data into JSON streams or use malicious JSON streams to modify application behavior. There are two types of JSON injections, server-side and client-side:

  • Server-side JSON injection happens when data from an untrusted source is not sanitized by the server and is written directly to a JSON stream.
  • Client-side JSON injection happens when data from an untrusted JSON source is not sanitized and is parsed directly using the JavaScript eval function.

What is JSON hijacking?

While JSON hijacking (a subset of cross-site script inclusion – XSSI) also involves the JSON format, it is a slightly different attack, in some ways similar to cross-site request forgery (CSRF). Attackers can use JSON hijacking to intercept JSON data sent from a web server to a web application. A typical JSON hijacking attack might look like this:

  1. The attacker creates a malicious website containing a script tag that references a JSON data URL of the web application under attack and includes code to hijack the JSON data.
  2. A user logged into the targeted web application is tricked into visiting the malicious website (usually using social engineering).
  3. Since the same-origin policy (SOP) allows JavaScript from any website to be included and executed in the context of any other site, the user’s web browser loads the JSON data in the context of the malicious site.
  4. The malicious website hijacks the JSON data.

Example of a server-side JSON injection attack

A simple server-side JSON injection could be performed in PHP as follows:

  1. The server stores user data as a JSON string, including the account type.
  2. User name and password values are taken directly from user input parameters without validation or sanitization.
  3. The JSON string is built using simple concatenation:
$json_string = '{"accountType":"user","userName":"'.$_GET['userName'].'","pass":"'.$_GET['pass'].'"}';
  1. A malicious user appends data to their user name entered into an input form or delivered in an HTTP header. This data is sent to the back-end unsanitized:
john%22,%22accountType%22:%22administrator%22
  1. The resulting JSON string stored by the application back-end is:
{
"accountType":"user",
"userName":"john",
"accountType":"administrator",
"pass":"password"
}
  1. When reading the stored string, the JSON parser (json_decode) encounters two accountType entries and accepts the last one, granting john administrator privileges without any authentication. Note that, strictly speaking, the behavior of json_decode is not incorrect – RFC-7159 for the JSON format states that “the names within an object SHOULD be unique” but not that they must be unique, leaving some room for interpretation.

Example of a client-side JSON injection attack

A simple client-side JSON injection could be performed as follows:

  1. The initial JSON string is the same as in the previous example.
  2. The server gets the JSON data, including a malicious payload, from an untrusted source and does not sanitize it.
  3. The client parses the JSON string using eval:
var result = eval("(" + json_string + ")");
document.getElementById("#accountType").innerText = result.account;
document.getElementById("#userName").innerText = result.name;
document.getElementById("#pass").innerText = result.pass;
  1. The accountType value injected by the attacker is:
user"});alert(document.cookie);({"accountType":"user
  1. The eval function executes the alert call.
  2. Parsing the malicious string results in a cross-site scripting (XSS) attack (document.cookie is disclosed).